package conson.tech.manage.common.util;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description: 导出工具类
 * @author: yuwenshuo
 * @since: 2020-04-08 10:12
 */

@Slf4j
public class ExcelUtils {


    /**
     * 获取excel表格值
     */
    public static String getCellValue(XSSFCell cell) {
        String value = null;
        switch (cell.getCellTypeEnum()) {
            case STRING:
                value = cell.getStringCellValue();
                break;
            //这个地方区别
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    value = cell.getDateCellValue().toString();
                } else {
                    value = cell.getNumericCellValue() + "";
                }
                break;
            case BLANK:
                value = "";
                break;
            default:
                break;
        }
        return value;
    }

    /**
     * 导出excel
     *
     * @param fileName
     * @param response
     * @param workbook
     * @param request
     */
    public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook, HttpServletRequest request) {
        fileName += ExcelTypeEnum.XLSX.getValue();
        String fileExportName;
        String agent = request.getHeader("USER-AGENT").toLowerCase();
        try {
            if (!agent.toLowerCase().contains("Mozilla".toLowerCase())) {
                fileExportName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileExportName = URLEncoder.encode(fileName, "UTF-8");
            }
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/form-data;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileExportName);
            workbook.write(response.getOutputStream());

        } catch (Exception e) {
            log.error("文件导出异常,详情如下:", e);
        } finally {
            try {
                if (workbook != null) {
                    //关闭输出流
                    workbook.close();
                }
            } catch (IOException e) {
                log.error("文件导出异常,详情如下:", e);
            }
        }
    }


    /**
     * 多sheet导出
     *
     * @param fileName
     * @param map
     * @param response
     * @param request
     */
    public static void exportExcel(String fileName, Map<String, List<? extends BaseRowModel>> map, HttpServletResponse response, HttpServletRequest request) {
        ServletOutputStream out = null;
        String agent = request.getHeader("USER-AGENT").toLowerCase();
        fileName += ExcelTypeEnum.XLSX.getValue();
        String fileExprotName;
        try {
            if (!agent.toLowerCase().contains("Mozilla".toLowerCase())) {
                fileExprotName = new String(fileName.getBytes(), "UTF-8");
            } else {
                fileExprotName = URLEncoder.encode(fileName, "UTF-8");
            }
            response.setContentType("multipart/form-data;charset=utf-8");
            //response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileExprotName);
            //response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            out = response.getOutputStream();
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
            setSheet(map, writer);
            writer.finish();
            out.flush();
        } catch (IOException e) {
            log.error("文件导出异常,详情如下:", e);
        } finally {
            try {
                if (out != null) {
                    //关闭输出流
                    out.close();
                }
            } catch (IOException e) {
                log.error("文件导出异常,详情如下:", e);
            }
        }
    }


    /**
     * 生成sheet页面信息，（可多个）
     *
     * @param sheetNameAndDateList
     * @param writer
     */
    private static void setSheet(Map<String, List<? extends BaseRowModel>> sheetNameAndDateList, ExcelWriter writer) {
        int sheetNum = 1;
        for (Map.Entry<String, List<? extends BaseRowModel>> stringListEntry : sheetNameAndDateList.entrySet()) {
            Sheet sheet = new Sheet(sheetNum, 0, stringListEntry.getValue().get(0).getClass());
            //设置列宽 设置每列的宽度
//            Map columnWidth = new HashMap();
//            for (int i=0;i<sheetNameAndDateList.size();i++){
//                columnWidth.put(i, BillInfoExportConstants.DEFAULT_COLUMN_WIDTH_INT);
//            }
//            sheet.setColumnWidthMap(columnWidth);
            sheet.setSheetName(stringListEntry.getKey());
            //sheet.setAutoWidth(Boolean.TRUE);
            writer.write(stringListEntry.getValue(), sheet);
            sheetNum++;
        }
    }


    /**
     * 简单导出
     *
     * @param fileName
     * @param clazz
     * @param dataList
     * @param response
     * @throws Exception
     */
    public static void export(String fileName, List dataList, Class clazz, HttpServletResponse response) throws Exception {

        fileName = fileName + "_" + System.currentTimeMillis() + ".xlsx";

        if (CollectionUtils.isEmpty(dataList)) {
            dataList.add(clazz.newInstance());
        }

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        EasyExcel.write(response.getOutputStream(), clazz).sheet().doWrite(dataList);

    }

    public static <T extends BaseRowModel> List<T> read(MultipartFile file, Class<T> rowModel) throws Exception {

        ExcelListener excelListener = new ExcelListener();
        ExcelReader excelReader = getExcelReader(multipartFileToFile(file), excelListener);
        if (excelReader == null) {
            return new ArrayList();
        }
        for (Sheet sheet : excelReader.getSheets()) {
            sheet.setClazz(rowModel);
            excelReader.read(sheet);
        }
        List<T> list = new ArrayList<>();
        for (Object obj : excelListener.getDataList()) {
            list.add((T) obj);
        }
        return list;
    }

    public static File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param file          文件
     * @param eventListener 用户监听器
     * @return
     */
    public static ExcelReader getExcelReader(File file,
                                             AnalysisEventListener eventListener) throws Exception {
        String fileName = file.getName();
        if (fileName == null) {
            throw new Exception("文件格式错误！");
        }
        if (!fileName.toLowerCase().endsWith(ExcelTypeEnum.XLS.getValue()) && !fileName.toLowerCase().endsWith(ExcelTypeEnum.XLSX.getValue())) {
            throw new Exception("文件格式错误！");
        }
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
            if (fileName.toLowerCase().endsWith(ExcelTypeEnum.XLS.getValue())) {
                return new ExcelReader(inputStream, ExcelTypeEnum.XLS, null, eventListener, false);
            } else {
                return new ExcelReader(inputStream, ExcelTypeEnum.XLSX, null, eventListener, false);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

}
